//
//  FilterManager.m
//  Cidney
//
//  Created by Chris Karr on 1/12/08.
//  Copyright 2008 __MyCompanyName__. All rights reserved.
//

#import "FilterManager.h"
#import "Dispatcher.h"
#import <AddressBook/AddressBook.h>
#import "Caller.h"

#define SAVED_FILTERS @"Saved Filters"
#define SELECTED_FILTERS @"Selected Filters"

@implementation FilterManager

@synthesize blacklist;

static FilterManager * sharedFilterManager = nil;

- (void) broadcastBlacklist:(NSTimer *) theTimer
{
	[[NSNotificationCenter defaultCenter] postNotificationName:BLACKLIST_BROADCAST 
														object:nil 
													  userInfo:[NSDictionary dictionaryWithObject:self.blacklist
																						   forKey:BLACKLIST]];
	
	[theTimer release];
}

- (void) save:(NSNotification *) theNote
{
	NSMutableArray * savedFilters = [NSMutableArray array];
	NSMutableArray * selectedFilters = [NSMutableArray array];
	
	for (NSDictionary * filter in [filters arrangedObjects])
	{
		NSMutableDictionary * savedFilter = [NSMutableDictionary dictionaryWithDictionary:filter];
		
		[savedFilter setValue:[[filter valueForKey:@"predicate"] predicateFormat] forKey:@"predicate"];
		[savedFilters addObject:savedFilter];
		
		if ([[filters selectedObjects] containsObject:filter])
			[selectedFilters addObject:[filter valueForKey:@"name"]];
	}
	
	[[NSUserDefaults standardUserDefaults] setValue:savedFilters forKey:SAVED_FILTERS];
	[[NSUserDefaults standardUserDefaults] setValue:selectedFilters forKey:SELECTED_FILTERS];
	
	[[NSUserDefaults standardUserDefaults] setValue:[self.blacklist allObjects] forKey:BLACKLIST];

	[[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(broadcastBlacklist:) userInfo:nil repeats:NO] retain];
}

- (void) load
{
	NSArray * savedFilters = [[NSUserDefaults standardUserDefaults] valueForKey:SAVED_FILTERS];
	NSArray * selectedFilters = [[NSUserDefaults standardUserDefaults] valueForKey:SELECTED_FILTERS];
	
	NSMutableArray * selects = [NSMutableArray array];
	
	if (savedFilters != nil)
	{
		for (NSDictionary * savedFilter in savedFilters)
		{
			NSMutableDictionary * filter = [NSMutableDictionary dictionaryWithDictionary:savedFilter];

			[filter setValue:[NSPredicate predicateWithFormat:[filter valueForKey:@"predicate"]] forKey:@"predicate"];
			
			[filters addObject:filter];
			
			if ([selectedFilters containsObject:[filter valueForKey:@"name"]])
				[selects addObject:filter];
		}
	}
	
	[filters setSelectedObjects:nil];
	[filters setSelectedObjects:selects];
	
	NSArray * savedBlacklist = [[NSUserDefaults standardUserDefaults] valueForKey:BLACKLIST];
	
	if (savedBlacklist == nil)
		savedBlacklist = [NSArray array];
	
	self.blacklist = [NSMutableSet setWithArray:savedBlacklist];
	
	[[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(broadcastBlacklist:) userInfo:nil repeats:NO] retain];
}


- (IBAction) addFilter:(id)sender
{
	NSMutableDictionary * filter = [NSMutableDictionary dictionary];
	[filter setValue:@"New Filter" forKey:@"name"];
	
	NSPredicate * predicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:
									[NSPredicate predicateWithFormat:@"(tags contains 'unknown') and (name contains 'Caller')"], nil]];

	[filter setValue:predicate forKey:@"predicate"];
	
	[filters addObject:filter];
}

- (void) awakeFromNib
{
	sharedFilterManager = self;
	
	[filters addObserver:self forKeyPath:@"arrangedObjects" options:0 context:NULL];
	[filters addObserver:self forKeyPath:@"selection" options:0 context:NULL];

	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(save:) name:NSApplicationWillTerminateNotification object:nil];
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(incoming:) name:INCOMING_CALL object:nil];

	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(blacklist:) name:BLACKLIST_CALL object:nil];

	[self load];
}

- (void) blacklist: (NSNotification *) msg
{
	NSDictionary * caller = [msg userInfo];
	
	NSDictionary * blacklistedCaller = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:[caller valueForKey:NAME_KEY], 
																			[caller valueForKey:NUMBER_KEY], nil] 
																   forKeys:[NSArray arrayWithObjects:NAME_KEY, NUMBER_KEY, nil]];
	
	[self willChangeValueForKey:@"blacklist"];
	[self.blacklist addObject:blacklistedCaller];
	[self didChangeValueForKey:@"blacklist"];
	
	[self save:msg];
}

- (IBAction) blacklistCall:(id) sender
{
	for (Caller * call in [calls selectedObjects])
	{
		NSString * name = [call valueForKey:@"name"];
		NSString * number = [call valueForKey:@"number"];

		NSDictionary * blacklistedCaller = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:[call valueForKey:@"name"], 
																				[call valueForKey:@"number"], nil] 
																	   forKeys:[NSArray arrayWithObjects:NAME_KEY, NUMBER_KEY, nil]];
		
		if (![self.blacklist member:blacklistedCaller])
		{
			NSString * msg = [NSString stringWithFormat:@"Should the caller '%@' (%@) be blacklisted?", name, number, nil];
	
			if (NSRunAlertPanel (NSLocalizedString (@"Blacklist Incoming Call", nil), msg, @"No", @"Yes", nil) == NSAlertAlternateReturn)
			{
				[self willChangeValueForKey:@"blacklist"];
				[self.blacklist addObject:blacklistedCaller];
				[self didChangeValueForKey:@"blacklist"];
				[self save:nil];
			}
		}
	}
}

- (void) incoming: (NSNotification *) msg
{
	NSDictionary * userInfo = [msg userInfo];
	
	ABPerson * person = [userInfo valueForKey:PERSON_KEY];
	NSString * number = [userInfo valueForKey:NUMBER_KEY];
	NSString * name = [userInfo valueForKey:NAME_KEY];

	Caller * call = [Caller dictionary];
	[call setValue:[NSDate date] forKey:@"date"];
	[call setValue:number forKey:@"number"];
	[call setValue:name forKey:@"name"];
	[call setValue:person forKey:PERSON_KEY];
	
	BOOL passed = YES;
	
	for (NSDictionary * filter in [filters selectedObjects])
	{
		NSPredicate * predicate = [filter valueForKey:@"predicate"];
		
		if (![predicate evaluateWithObject:call])
			passed = NO;
	}
	
	NSDictionary * blacklistTest = [NSDictionary dictionaryWithObjectsAndKeys:name, NAME_KEY, number, NUMBER_KEY, nil];
	
	if ([self.blacklist member:blacklistTest])
		passed = NO;
	
	if (passed)
		[[NSNotificationCenter defaultCenter] postNotificationName:FILTERED_CALL object:self userInfo:userInfo];
	
	[[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(broadcastBlacklist:) userInfo:nil repeats:NO] retain];
}

- (void) selectFilterWithTitle:(NSString *) title
{
	[filters setSelectedObjects:nil];
	
	for (NSDictionary * filter in [filters arrangedObjects])
	{
		if ([[filter valueForKey:@"name"] isEqual:title])
			[filters setSelectedObjects:[NSArray arrayWithObject:filter]];
	}
}

- (void)observeValueForKeyPath:(NSString *) keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqual:@"arrangedObjects"]) 
	{
		for (NSMenuItem * item in [filterMenu itemArray])
			[filterMenu removeItem:item];

		NSMenuItem * none = [filterMenu addItemWithTitle:@"No Filter" action:@selector(switchFilter:) keyEquivalent:@""];
		[none setTarget:self];
	
		[filterMenu addItem:[NSMenuItem separatorItem]];
		
		for (NSDictionary * filter in [filters arrangedObjects])
		{
			NSMenuItem * item = [filterMenu addItemWithTitle:[filter valueForKey:@"name"] action:@selector(switchFilter:) keyEquivalent:@""];
			
			[item bind:@"title" toObject:filter withKeyPath:@"name" options:nil];
			[item setTarget:self];
		}
	}
	else if ([keyPath isEqual:@"selection"]) 
	{
		NSArray * selection = [filters selectedObjects];
		
		NSString * title = @"No Filter";
		
		if ([selection count] > 0)
			title = [[selection objectAtIndex:0] valueForKey:@"name"];

		for (NSMenuItem * item in [filterMenu itemArray])
		{
			[item setState:NSOffState];

			if ([[item title] isEqualToString:title])
				[item setState:NSOnState];
		}
	}
}

- (IBAction) switchFilter:(id) sender
{
	for (NSMenuItem * item in [filterMenu itemArray])
	{
		if (item != sender)
			[item setState:NSOffState];
		else
		{
			[self selectFilterWithTitle:[item title]];
			[item setState:NSOnState];
		}
	}
}

- (NSArray *) allFilterNames
{
	NSMutableArray * filterNames = [NSMutableArray array];
	
	for (NSDictionary * filter in [filters arrangedObjects])
	{
		NSString * filterName = [filter valueForKey:@"name"];
		
		if (filterName != nil)
			[filterNames addObject:filterName];
	}
	
	[filterNames sortUsingSelector:@selector(compare:)];
	
	return filterNames;
}

+ (FilterManager *) sharedFilterManager
{
	return sharedFilterManager;
}

- (void) doTerminate:(NSNotification *) note;
{
	if(sharedFilterManager)
	   [sharedFilterManager release];
}

- (IBAction) resetBlacklist:(id) sender
{
	self.blacklist = [NSMutableSet set];
	
	[self save:nil];
}


@end
